import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import numpy as np
from plotly.offline import init_notebook_mode
init_notebook_mode()
df = pd.read_csv('capture_fisheries.csv', skiprows=4)
df = df.dropna(how='all')
df['Country Name'] = df['Country Name'].str.replace('"', '')
years = [str(year) for year in range(1960, 2025)]
id_vars = ["Country Name", "Country Code", "Indicator Name", "Indicator Code"]
df_melted = df.melt(id_vars=id_vars, value_vars=years,
var_name="Year", value_name="Production")
df_melted['Year'] = pd.to_numeric(df_melted['Year'])
df_melted['Production'] = pd.to_numeric(df_melted['Production'], errors='coerce')
df_melted = df_melted.dropna(subset=['Production'])
q95 = df_melted['Production'].quantile(0.95)
focused_data = df_melted[df_melted['Production'] <= q95]
zmax = focused_data['Production'].max()
zmin = focused_data['Production'].min()
enhanced_scale = [
[0.0, '#E1F5FE'],
[0.1, '#B3E5FC'],
[0.2, '#81D4FA'],
[0.3, '#4FC3F7'],
[0.4, '#29B6F6'],
[0.5, '#039BE5'],
[0.6, '#0288D1'],
[0.7, '#0277BD'],
[0.8, '#01579B'],
[0.9, '#0D47A1'],
[1.0, '#1d1c47']
]
total_production = df_melted.groupby(['Country Name', 'Country Code'])['Production'].sum().reset_index()
fig_total = px.choropleth(total_production,
locations="Country Code",
color="Production",
hover_name="Country Name",
color_continuous_scale=enhanced_scale,
range_color=[zmin, zmax],
labels={'Production': 'Production (metric tons)'},
projection="natural earth")
fig_total.update_layout(
width=700,
geo=dict(
landcolor='#f0f0f0',
lakecolor='#d0e0f0',
bgcolor='white',
showframe=True,
framecolor='black'
),
coloraxis_colorbar=dict(
title="Production",
thickness=20,
len=0.75,
tickvals=np.linspace(zmin, zmax, 6),
ticktext=[f"{int(x):,}" for x in np.linspace(zmin, zmax, 6)]
),
margin={'t': 0, 'r': 20, 'b': 21, 'l': 18},
title={
'text': '<b>Total Fisheries Production per Country</b>',
'x': 0.42,
'xanchor': 'center',
'font': {
'color': '#0a2463',
}
}
)
frames = []
for year in sorted(df_melted['Year'].unique()):
yearly_data = df_melted[df_melted['Year'] == year]
yearly_focused = yearly_data[yearly_data['Production'] <= yearly_data['Production'].quantile(0.95)]
year_zmax = yearly_focused['Production'].max()
year_zmin = yearly_focused['Production'].min()
frames.append(go.Frame(
data=[go.Choropleth(
locations=yearly_data['Country Code'],
z=yearly_data['Production'],
zmin=year_zmin,
zmax=year_zmax,
colorscale=enhanced_scale,
customdata=yearly_data[['Country Name']],
hovertemplate="<b>%{customdata[0]}</b><br>" +
"Year: %{frame.name}<br>" +
"Production: %{z:,} metric tons<extra></extra>",
marker_line_color='darkgray',
marker_line_width=0.5
)],
name=str(year)
))
fig_slider = go.Figure(
data=[go.Choropleth(
locations=df_melted['Country Code'],
z=df_melted['Production'],
colorscale=enhanced_scale,
customdata=df_melted[['Country Name']],
hovertemplate="<b>%{customdata[0]}</b><br>" +
"Year: %{frame.name}<br>" +
"Production: %{z:,} metric tons<extra></extra>",
marker_line_color='darkgray',
marker_line_width=0.5
)],
layout=go.Layout(
width=700,
height=500,
geo=dict(
domain={'x': [0, 0.9], 'y': [0, 1]},
showframe=True,
showcoastlines=True,
landcolor='#f0f0f0',
lakecolor='#d0e0f0',
bgcolor='white',
framecolor='black',
framewidth=1
),
margin={'t': 30, 'r': 20, 'b': 200, 'l': 30},
title={
'text': '<b>Annual Fisheries Production per Country</b>',
'x': 0.42,
'xanchor': 'center',
'font': {
'color': '#0a2463',
}
},
sliders=[{
"active": 0,
"steps": [{
"args": [[f.name], {"frame": {"duration": 300, "redraw": True},
"mode": "immediate"}],
"label": f.name,
"method": "animate"
} for f in frames],
"x": 0.15,
"len": 0.7,
"currentvalue": {
"prefix": "<b>Year: </b>",
"font": {"size": 14},
"xanchor": "center"
}
}],
updatemenus=[{
"buttons": [
{
"args": [None, {"frame": {"duration": 400, "redraw": True},
"fromcurrent": True}],
"label": "Play",
"method": "animate"
},
{
"args": [[None], {"frame": {"duration": 0, "redraw": True},
"mode": "immediate"}],
"label": "Pause",
"method": "animate"
}
],
"type": "buttons",
"x": 0.1,
"y": -0.05,
"bgcolor": "rgba(255,255,255,0.8)",
"bordercolor": "#444"
}]
),
frames=frames,
)
fig_total.add_annotation(x=0.02, y=-0.18,
xref="paper", yref="paper",
showarrow=False,
align='left',
xanchor='left', yanchor='bottom',
text="Total fisheries production per country since 1960.<br>" + \
'Hover over countries to see their specific production and drag to see different areas.<br>')
fig_total.update_annotations(
font=dict(color='#0a2463')
)
fig_slider.add_annotation(x=0, y=-0.60,
xref="paper", yref="paper",
showarrow=False,
align='left',
xanchor='left', yanchor='bottom',
text="Annual fisheries production per country since 1960.<br>" + \
'Use slider to see different years or press play to see time progression.<br>' + \
'Color scale automatically focuses on 95% of data for each year. <br>')
fig_slider.update_annotations(
font=dict(color='#0a2463')
)
fig_total.show()
fig_slider.show()
---------------------------------------------------------------------------
FileNotFoundError Traceback (most recent call last)
Cell In[1], line 9
6 from plotly.offline import init_notebook_mode
7 init_notebook_mode()
----> 9 df = pd.read_csv('capture_fisheries.csv', skiprows=4)
10 df = df.dropna(how='all')
12 df['Country Name'] = df['Country Name'].str.replace('"', '')
File ~/miniconda3/lib/python3.13/site-packages/pandas/io/parsers/readers.py:1026, in read_csv(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, skipfooter, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, date_format, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, doublequote, escapechar, comment, encoding, encoding_errors, dialect, on_bad_lines, delim_whitespace, low_memory, memory_map, float_precision, storage_options, dtype_backend)
1013 kwds_defaults = _refine_defaults_read(
1014 dialect,
1015 delimiter,
(...) 1022 dtype_backend=dtype_backend,
1023 )
1024 kwds.update(kwds_defaults)
-> 1026 return _read(filepath_or_buffer, kwds)
File ~/miniconda3/lib/python3.13/site-packages/pandas/io/parsers/readers.py:620, in _read(filepath_or_buffer, kwds)
617 _validate_names(kwds.get("names", None))
619 # Create the parser.
--> 620 parser = TextFileReader(filepath_or_buffer, **kwds)
622 if chunksize or iterator:
623 return parser
File ~/miniconda3/lib/python3.13/site-packages/pandas/io/parsers/readers.py:1620, in TextFileReader.__init__(self, f, engine, **kwds)
1617 self.options["has_index_names"] = kwds["has_index_names"]
1619 self.handles: IOHandles | None = None
-> 1620 self._engine = self._make_engine(f, self.engine)
File ~/miniconda3/lib/python3.13/site-packages/pandas/io/parsers/readers.py:1880, in TextFileReader._make_engine(self, f, engine)
1878 if "b" not in mode:
1879 mode += "b"
-> 1880 self.handles = get_handle(
1881 f,
1882 mode,
1883 encoding=self.options.get("encoding", None),
1884 compression=self.options.get("compression", None),
1885 memory_map=self.options.get("memory_map", False),
1886 is_text=is_text,
1887 errors=self.options.get("encoding_errors", "strict"),
1888 storage_options=self.options.get("storage_options", None),
1889 )
1890 assert self.handles is not None
1891 f = self.handles.handle
File ~/miniconda3/lib/python3.13/site-packages/pandas/io/common.py:873, in get_handle(path_or_buf, mode, encoding, compression, memory_map, is_text, errors, storage_options)
868 elif isinstance(handle, str):
869 # Check whether the filename is to be opened in binary mode.
870 # Binary mode does not support 'encoding' and 'newline'.
871 if ioargs.encoding and "b" not in ioargs.mode:
872 # Encoding
--> 873 handle = open(
874 handle,
875 ioargs.mode,
876 encoding=ioargs.encoding,
877 errors=errors,
878 newline="",
879 )
880 else:
881 # Binary mode
882 handle = open(handle, ioargs.mode)
FileNotFoundError: [Errno 2] No such file or directory: 'capture_fisheries.csv'